import * as THREE from "three"
import initRenderer from "./core/renderer";
import { model as granary, granaryArr } from "./core/model";
import initScene from "./core/scene";
import { labelRenderer, tag } from "./core/tag";
import { choose } from "./core/util";
import messageData from "./core/messageData";
import { TWEEN } from 'three/examples/jsm/libs/tween.module.min.js';
import { Vector3 } from "three";

class Box {
    private scene;
    private camera;
    private renderer;
    private container;
    private tagMesh;
    private messageTagData;
    private time = 0;
    private num = 15;   //火焰的帧数
    private textures = [];
    private stopAnimationFrame = null;

    constructor(container, messageTag, messageTagData) {
        this.container = container;
        this.messageTagData = messageTagData;
        this.tagMesh = tag(messageTag);
        this.scene = new THREE.Scene();
        this.init();
    }
    init() {
        // 初始化渲染器和相机
        let { renderer, camera, render } = initRenderer({ scene: this.scene, container: this.container, labelRenderer: labelRenderer(this.container) });
        this.renderer = renderer;
        this.camera = camera;
        this.renderer.setClearColor("black");

        // 初始化场景
        initScene({ scene: this.scene, container: this.container, renderer: this.renderer, camera: this.camera });

        //初始化模型
        this.initObjects();

        // 开始渲染
        render();
    }

    //绘制
    initObjects() {
        //雾化
        this.scene.fog = new THREE.Fog("black", 1, 1000);
        //导入粮仓模型
        this.scene.add(granary);

        //初始化交互
        this.initInteraction();

        setTimeout(() => {
            this.fire("P_05");
            const flame = this.fire("Q_05");
            setTimeout(() => {
                this.scene.remove(flame);
            }, 2000);
        }, 2000);
        this.animate();
    }

    // 点击粮仓方式，显示信息交互
    initInteraction() {
        const that = this;
        //点击模型说明标签
        this.scene.add(this.tagMesh);
        this.container.addEventListener("click", choose({
            camera: this.camera,
            granaryArr: granaryArr,
            container: this.container,
            success(chooseMesh) {
                that.tagMesh.element.style.visibility = 'visible';//显示标签        
                // messageTag.position.copy(chooseMesh.getWorldPosition());//通过粮仓世界坐标设置标签位置
                that.tagMesh.position.copy(chooseMesh.point);//射线在粮仓表面拾取坐标
                Object.keys(that.messageTagData).forEach(key => {
                    that.messageTagData[key] = messageData[chooseMesh.name][key];
                });

                new TWEEN.Tween({ weight: 0 })
                    .to({ weight: that.messageTagData["weight"] }, 500)
                    .easing(TWEEN.Easing.Quadratic.In)
                    .onUpdate(function (object) {
                        that.messageTagData["weight"] = Math.ceil(object.weight);
                    })
                    .start()

            }
        }));
    }

    // 绘制火焰
    fire(name) {
        const pos = new Vector3();
        const geometry = granary.getObjectByName(name);
        geometry.getWorldPosition(pos);
        // let flame2 = this.createFlame('/model/flame/火焰test.png');
        let flame = this.createFlame('/model/flame/火焰.png');

        if (geometry.parent.name == "立筒仓") {
            flame.position.y += 36;//加上粮仓顶部高度
        } else if (geometry.parent.name == "浅圆仓") {
            flame.position.y += 20;
        } else if (geometry.parent.name == "平房仓") {
            flame.position.y += 17;
        }

        flame.position.copy(pos);
        this.scene.add(flame);
        return flame;
    }

    // 创建火焰
    createFlame(modelPath) {
        var w = 60;//火焰宽度  通过参数w可以快速调节火焰大小，以便于适应对应的三维场景
        var h = 1.6 * w;//火焰高度
        const geometry = new (THREE as any).PlaneBufferGeometry(w, h); //矩形平面
        geometry.translate(0, h / 2, 0);//火焰底部中点和局部坐标系坐标原点重合

        var textureLoader = new THREE.TextureLoader();//纹理贴图加载器
        const texture = textureLoader.load(modelPath);//创建一个纹理对象
        texture.repeat.set(1 / this.num, 1);// 1/num：从图像上截图一帧火焰，可以理解成横纵向截取的百分比 (uv两个方向纹理重复数量)
        // texture.offset.x = 1 / this.num;//选择第1帧火焰
        // texture.offset.x = 1 / this.num;//选择第2帧火焰
        // texture.offset.x = (this.num-1) / this.num;//选择第一帧火焰
        var material = new THREE.MeshBasicMaterial({
            map: texture,
            transparent: true,
            side: THREE.DoubleSide, //双面可见
        });
        const flame = new THREE.Group();
        const mesh = new THREE.Mesh(geometry, material);// 火焰网格模型
        // flame.add(mesh);
        flame.add(mesh, mesh.clone().rotateY(Math.PI / 2), mesh.clone().rotateY(Math.PI / 4), mesh.clone().rotateY(Math.PI * 3 / 4));
        this.textures.push(texture);

        flame["stop"] = () => {
            window.cancelAnimationFrame(this.stopAnimationFrame);//取消动画
        }
        return flame;
    }

    // 启动火焰动画
    animate() {
        this.time += 0.1;//调节火焰切换速度
        if (this.time > this.num) this.time = 0;
        //  Math.floor(t)取整 保证一帧一帧切换
        this.textures.forEach(tt => {
            tt.offset.x = Math.floor(this.time) / this.num;// 动态更新纹理偏移 播放关键帧动画 产生火焰然后效果
        });
        this.stopAnimationFrame = requestAnimationFrame(this.animate.bind(this));
    }

}

export default Box;